package com.spring.cloud.eurekaclientgateway.filter;

import brave.Tracer;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.spring.cloud.eurekaclientgateway.EurekaClientGatewayApplication;
import io.github.resilience4j.ratelimiter.RateLimiter;
import io.github.resilience4j.ratelimiter.RateLimiterRegistry;
import io.vavr.control.Try;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import com.spring.cloud.commonutils.vo.UserInfo;
import com.spring.cloud.commonutils.vo.ResultMessage;

import java.util.concurrent.Callable;


//使用GatewayFilter 接口方式实现局部过滤器
//或者通过OrderedGatewayFilter 也可以进行局部过滤器排序,但是最后返回的是 new OrderedGatewayFilter(filter,order);
@Component
public class RateLimiterGatewayFilter implements GatewayFilter, Ordered {

    //resilience4j 注册机
    @Autowired
    private RateLimiterRegistry rateLimiterRegistry;

    @Autowired
    private Tracer tracer;
    private static final Logger logger = LoggerFactory.getLogger(EurekaClientGatewayApplication.class);

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        //自定义Tace
        //添加一个span的属性标记
        tracer.currentSpan().tag("1001","GET请求");
        //当前trace id
        String traceId = tracer.currentSpan().context().traceIdString();
        String spanId = tracer.currentSpan().context().spanIdString();
        logger.info("当前追踪参数: traceId={},spanId={}",traceId,spanId);



        //执行 Resilience4j限速器
        ResultMessage resultMessage = rateLimiter();
        //不放行逻辑
        if(!resultMessage.isSuccess()){
            //获取响应对象
            ServerHttpResponse response = exchange.getResponse();
            //设置响应状态码429--请求过多
            response.setStatusCode(HttpStatus.TOO_MANY_REQUESTS);
            //设置响应头 类型为json
            response.getHeaders().setContentType(MediaType.valueOf(MediaType.APPLICATION_JSON_VALUE));
            //转JSON
            String body = toJson(resultMessage);
            //响应数据放入缓冲区
            DataBuffer dataBuffer = response.bufferFactory().wrap(body.getBytes());
            //使用限流结果响应请求,不在继续执行过滤器链
            return response.writeWith(Mono.just(dataBuffer));
        }
        //放行,继续执行过滤器链
        return chain.filter(exchange);
    }

    //获取一个resilience4j 的限速器 ratelimiter
    private ResultMessage rateLimiter(){

        RateLimiter rateLimiter = rateLimiterRegistry.rateLimiter("user");
        Callable<ResultMessage> call = RateLimiter.decorateCallable(rateLimiter,()-> new ResultMessage(true,"PASS"));
        Try<ResultMessage> tryResult = Try.of(()->call.call())
                .recover(ex->new ResultMessage(false,"TOO MANY REQUESTS"));
        ResultMessage result = tryResult.get();
        return result;
    }

    //ResultMessage对象转JSON
    private String toJson(ResultMessage result)  {
        ObjectMapper mapper = new ObjectMapper();
        String body = null;
        try{
            body = mapper.writeValueAsString(result);
        }catch (JsonProcessingException ex){
            ex.printStackTrace();
        }
        return body;
    }

    @Override
    public int getOrder() {
        return HIGHEST_PRECEDENCE + 100002;
    }
}
